﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Linq;

namespace CssAndJsCombiner.Configuration
{
    public class ClientResourceGroupCollection : ConfigurationElementCollection
    {
        private Dictionary<string, IList<ClientResourceItemElement>> groups;

        public override ConfigurationElementCollectionType CollectionType
        {
            get { return ConfigurationElementCollectionType.AddRemoveClearMap; }
        }

        public ClientResourceGroupElement this[int index]
        {
            get { return (ClientResourceGroupElement)BaseGet(index); }
            set
            {
                if (BaseGet(index) != null) BaseRemoveAt(index);
                BaseAdd(index, value);
            }
        }

        public void Add(ClientResourceGroupElement element)
        {
            BaseAdd(element);
        }

        public void Clear()
        {
            BaseClear();
        }

        public void Remove(ClientResourceGroupElement element)
        {
            BaseRemove(element);
        }

        public void RemoveAt(int index)
        {
            BaseRemoveAt(index);
        }

        protected override ConfigurationElement CreateNewElement()
        {
            return new ClientResourceGroupElement();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            ClientResourceGroupElement e = (ClientResourceGroupElement)element;
            return e.Name;
        }

        public Dictionary<string, IList<ClientResourceItemElement>> Items
        {
            get
            {
                if (groups == null)
                {
                    groups = new Dictionary<string, IList<ClientResourceItemElement>>();

                    foreach (ClientResourceGroupElement group in this)
                    {
                        IList<ClientResourceItemElement> items = getItems(this.Cast<ClientResourceGroupElement>(), group.Name);
                        groups.Add(group.Name.ToLowerInvariant(), items);
                    }
                }

                return groups;
            }
        }

        private IList<ClientResourceItemElement> getItems(IEnumerable<ClientResourceGroupElement> groups, string groupName)
        {
            ClientResourceGroupElement group = groups.SingleOrDefault(i => i.Name == groupName);
            if (group == null) throw new ArgumentException("Unrecognized group name", "group");

            IList<ClientResourceGroupElement> inheritsMap = new Collection<ClientResourceGroupElement>();
            inheritsMap.Add(group);

            while (group != null && !String.IsNullOrEmpty(group.Inherits))
            {
                group = groups.SingleOrDefault(i => i.Name == group.Inherits);
                if (group != null) inheritsMap.Add(group);
            }

            IList<ClientResourceItemElement> items = new Collection<ClientResourceItemElement>();
            foreach (ClientResourceGroupElement g in inheritsMap.Reverse())
            {
                foreach (ClientResourceItemElement item in g.Items)
                {
                    items.Add(item);
                }
            }

            return items;
        }
    }
}
